import socket,time,select,selectors
import os
ip_port=('localhost',1234)
BASE_DIR=os.path.dirname(os.path.abspath(__file__))
print(BASE_DIR)
class serverSelectors(object):

    def __init__(self):
        self.dict={}
        self.hasReceived=0
        self.sel = selectors.DefaultSelector()# select,pool,epool 操作系统自己选择一个
        self.create_socket()
        self.handle()

    def create_socket(self):
        sk = socket.socket()
        sk.bind(ip_port)
        sk.listen(5)
        sk.setblocking(False)
        self.sel.register(socket,selectors.EVENT_READ,self.accept)
        print("服务器已启动等待链接")

    def handle(self):
        while True:
            print("waiting for connect")
            evevts = self.sel.select()#[socket,conn] 真正的监听

            print(evevts)
            for key,mask in evevts:
                print(key)
                print(mask)
                callback = key.data # socket或者conn(key中绑定的函数)
                callback(key.fileobj,mask) # 监听的对象

    def accept(self,socket,mask):
        conn, addr = socket.accept()
        print('accpeted',conn,"from",addr)
        conn.setblocking(False) # 设置conn 为非阻塞

        self.sel.register(conn, selectors.EVENT_READ, self.read)

        self.dict[conn]={}

    def read(self,conn,make):
        try:
            if not self.dict[conn]:
                data=conn.recv(1024)
                cmd,filename,filesize = str(data,encoding="utf-8").split("|")
                self.dict={conn:{"cmd":cmd,"filename":filename,"filesize":int(filesize)}}

                if cmd=="put":
                    conn.send(bytes("ok",encoding="utf-8"))

                if self.dict[conn][cmd]=="get":
                    file=os.path.join(BASE_DIR,"download",filename)
                    if os.path.exists(file):
                        self.fileSize = os.path.getsize(file)
                        send_info="%s|%s" %(filename,self.fileSize)
                        conn.send(bytes(send_info,encoding="utf-8"))
                    else:
                        send_info="%s|%s"%("NO",0)
                        conn.send(bytes(send_info,encoding="utf-8"))
            else:
                if self.dict[conn].get("cmd",None):
                    cmd =self.dict[conn].get("cmd")
                    if hasattr(self,cmd):
                        func =getattr(self,cmd)
                        func(conn)
                    else:
                        print("error cmd")
        except Exception as e:
            print("error ",e)
            self.sel.unregister(conn)
            conn.close()

    def put(self,conn):
        fileName =self.dict["conn"].get("filename")
        path=os.path.join(BASE_DIR,"downlaod",fileName)
        recv_data=conn.recv(1024)
        self.hasReceived +=len(recv_data)

        with open(path,"ab") as f:
            f.write(recv_data)
        if self.fileSize==self.hasReceived:
            if conn in self.dict.keys():
                self.dict["conn"]={}  # 上传完毕、清空字典
            print("%s 上传完成" %fileName)

    def get(self,conn):
        self.hasSend = 0
        filename=self.dict["conn"].get("filename")

        path=os.path.join(BASE_DIR,"download",filename)

        with open(path,'ab') as f:
            f.seek(self.hasSend)
            for line in f:
                send_data=conn.sendall(line)
                self.hasSend +=len(send_data)

        if self.fileSize==self.hasReceived:
            if conn in self.dict.keys():
                self.dict["conn"]={}  # 上传完毕、清空字典
            print("%s 下载传输完成" % filename)
        self.dict["conn"] ={}
        print("文件下载完毕")

if __name__ == '__main__':
    serverSelectors()